﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;

namespace SensorVisual
{
    public partial class Calibracion : Form
    {
        private Movimiento movAcumulado;
        private Servo servoPan;

        private bool aplicada;
        public bool Aplicada
        {
            get { return aplicada; }
        }
        

        public Calibracion()
        {
            InitializeComponent();

            servoPan = new Servo();

            aplicada = true;
            comboBoxPortNames.DataSource = SerialPort.GetPortNames();
            comboBoxPortNames.SelectedIndex = SerialPort.GetPortNames().Length - 1;
            serialPort1.PortName = (string)comboBoxPortNames.SelectedItem;
            servoPan.Puerto = serialPort1;
        }

        private void comboBoxPortNames_TextChanged(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
                serialPort1.Close();

            serialPort1.PortName = (string)comboBoxPortNames.SelectedItem;
        }

        private void buttonCalibrar_Click(object sender, EventArgs e)
        {
            HabilitarBotones(false);
            aplicada = false;

            Thread t = new Thread(delegate()
            {
                if (rbPan.Checked)
                {
                    movAcumulado = Movimiento.Nulo;
                    servoPan.Posicion = 0;
                    System.Threading.Thread.Sleep(2000);

                    Sensor.SensorChangeHandler sch = new Sensor.SensorChangeHandler(sensor_OnSensorChange);
                    Sensor.Instance.OnSensorChange += sch;

                    for (float i = 0; i <= 180; i += 0.8f)
                    {
                        servoPan.Posicion = i;
                        System.Threading.Thread.Sleep(10);
                    }

                    Sensor.Instance.OnSensorChange -= sch;
                    SafeInvokeHelper.Invoke(this, "HabilitarBotones", true);
                }
                else if (rbTilt.Checked)
                {
                    MessageBox.Show("No hay un servo conectado para realizar el \nmovimiento de tilt de la camara");
                }
                else if (rbRot.Checked)
                {
                    MessageBox.Show("No hay un servo conectado para realizar el \nmovimiento de rotación de la camara");
                }
            });
            t.Start();

            buttonAceptar.Enabled = true;
            buttonCancelar.Enabled = true;
        }

        private void sensor_OnSensorChange(object sender, EventArgs e)
        {
            SafeInvokeHelper.Invoke(this, "safe_sensor_OnSensorChange", sender, e);
        }

        public void safe_sensor_OnSensorChange(object sender, EventArgs e)
        {
            movAcumulado += ((SensorChangeArgs)e).Movimiento;
            float desv = 180 + movAcumulado.pan;
            this.labelDesvPan.Text = desv.ToString();
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(
                    new SerialDataReceivedEventHandler(serialPort1_DataReceived), 
                    new object[] { sender, e });
            }
            else
            {
                int bytesNumber = serialPort1.BytesToRead;
                char[] buffer = new char[bytesNumber];
                serialPort1.Read(buffer, 0, bytesNumber);

                string salida = new String(buffer);
                salida = salida.Replace("\n\r", "\r\n");
                textBoxSalida.Text += salida;
            }
        }

        private void serialPort1_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(
                    new SerialErrorReceivedEventHandler(serialPort1_ErrorReceived),
                    new object[] { sender, e });
            }
            else
            {
                textBoxSalida.Text += "Error:" + e.ToString() + "\n";
            }
        }

        private void Calibracion_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen)
                serialPort1.Close();
        }

        private void buttonAplicar_Click(object sender, EventArgs e)
        {
            EstablecerCorreccion();
        }

        public void HabilitarBotones(bool habilitar)
        {
            buttonAceptar.Enabled = habilitar;
            buttonAplicar.Enabled = habilitar;
            buttonCancelar.Enabled = habilitar;
        }

        public void EstablecerCorreccion()
        {
            aplicada = true;
            float factorPan = 180 / Math.Abs(movAcumulado.pan);

            Sensor.Instance.ActualizarCorreccion(new Movimiento(factorPan, 1, 1, 1));
            buttonAplicar.Enabled = false;
        }
    }
}